//
//  Request.swift
//  Nairacup
//
//  Created by ec on 2024/9/19.
//

import Foundation
import CryptoSwift

struct DeviceModel {
    var phone: String
    var code: String
    // 手机品牌
    var mobilePhoneBrands: String
    // 应用市场编码
    var appMarketCode: String
    // af用户唯一标识id
    var appsFlyerId: String
    // 设备型号
    var deviceModel: String
    // 渠道（af获取) organic、googleadwords_int、Facebook Ads、Twitter、Palm、shalltry_int、restricted
    var channelCode: String
    // app版本
    var version: String
    // ios
    var client: String
    // af/谷歌拿到的数据（json字符串）
    var extensionS: String
    // adjust用户唯一 标识id
    var adjustId: String
}

enum Api {
    // 获取短信验证码
    case sendCode(phone: String)
    // 登录
    case login(device: DeviceModel)
    // 静默登录
    case staticLogin(version: String)
    // 退出登录
    case logout
    // 获取协议
    case getProtocol
    // 上传图片
    case uploadImg
    // 获取系统版本
    case getVersion
    // 用户埋点
    case uploadIosAction([String: Any])
    // 上传权限信息
    case uploadIosAuth(_ deviceInfo: [String: Any], location: [String: Any]? = nil, calendarList: [[String: Any]]? = nil)
        
    var path: String {
        switch self {
        case .sendCode:
            return "account/sendVerifyCode"
        case .login:
            return "account/loginByPhoneVerifyCode"
        case .staticLogin:
            return "account/staticLoginv2"
        case .logout:
            return "account/logout"
        case .getProtocol:
            return "system/getProtocolUrlv2"
        case .uploadImg:
            return "system/uploadimg"
        case .getVersion:
            return "system/getNewVersion"
        case .uploadIosAction:
            return "auth/uploadIosAction"
        case .uploadIosAuth:
            return "auth/uploadIosAuth"
        }
    }
    
    var parameters: [String: Any] {
        switch self {
        case .sendCode(let phone):
            return ["phone": phone]
        case .login(let device):
            return ["phone": device.phone,
                    "code": device.code,
                    "mobilePhoneBrands": device.mobilePhoneBrands,
                    "appMarketCode": device.appMarketCode,
                    "appsFlyerId": device.appsFlyerId,
                    "deviceModel": device.deviceModel,
                    "channelCode": device.channelCode,
                    "version": device.version,
                    "client": device.client,
                    "extension": device.extensionS,
                    "adjustId": device.adjustId]
        case .staticLogin(let version):
            return ["version": version]
        case .uploadIosAction(let p):
            return p
        case .uploadIosAuth(let deviceInfo, let location, let calendarList):
            var p: [String: Any] = ["deviceInfo": deviceInfo]
            if let location = location {
                p["location"] = location
            }
            if let calendarList = calendarList {
                p["calendarList"] = calendarList
            }
            return p
        default:
            return [:]
        }
    }
    
    var service: String {
        return ""
    }
    
    var headers: [String: String] {
        var h: [String: String] = [
            "appName": Adapt.appName,
            "devName": "ios",
            "appVersion": "1.0.0",
        ]
        if let userId = UserDefaults.standard.string(forKey: Adapt.loginUserId) as String?, !userId.isEmpty {
            h["userId"] = userId
        }
        if let sessionId = UserDefaults.standard.string(forKey: Adapt.loginSessionId) as String?, !sessionId.isEmpty {
            h["session"] = sessionId
        }
        return h
    }
    
    var method: String {
        return "POST"
    }
    
    var domain: String {
        return "http://121.41.164.237:7004/"
    }
}

typealias ResponseClosure = (_ response: [String: Any]) -> Void

class Request {
    static let shared = Request()
    
    func requestApi(_ api: Api, responseClosure: ResponseClosure? = nil) {
        let url = URL(string: api.domain + api.service + Request.aesEncrypt(api.path))!
        print("api.path=======>\(api.path)")
        var request = URLRequest(url: url)
        request.httpMethod = api.method
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        for (k, v) in api.headers {
            request.setValue("\(v)", forHTTPHeaderField: k)
        }
        let parameters: [String: Any] = api.parameters
        do {
            let jsonData = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
            if let jsonString = String(data: jsonData, encoding: .utf8) {
                if let data = Request.aesEncrypt(jsonString).data(using: .utf8) {
                    request.httpBody = data
                }
            }
        } catch {
            print("Error serializing JSON: \(error.localizedDescription)")
        }
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            if let error = error {
                Async.main {
                    responseClosure?(["code": 0, "message": "Error: \(error.localizedDescription)"])
                }
                return
            }
            if let data = data {
                if let responseString = String(data: data, encoding: .utf8) {
                    let str = Request.aesdecrypt(responseString)
                    if let jsonData = str.data(using: .utf8) {
                        do {
                            if let json = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
                                Async.main {
                                    // 拦截token失效
                                    if json["code"] as? Int == 411 || json["code"] as? Int == 2021 {
                                        UserDefaults.standard.removeObject(forKey: Adapt.loginSessionId)
                                        UserDefaults.standard.removeObject(forKey: Adapt.loginUserId)
                                        UserDefaults.standard.removeObject(forKey: Adapt.loginUserPhone)
                                        UserDefaults.standard.removeObject(forKey: Adapt.loginUserInfo)
                                        NotificationCenter.default.post(name: NSNotification.Name(Adapt.loginStatusChanged), object: nil)
                                    }
                                    responseClosure?(json)
                                }
                            }
                        } catch {
                            Async.main {
                                responseClosure?(["code": 0, "message": "JSON 解析失败: \(error)"])
                            }
                        }
                    } else {
                        Async.main {
                            responseClosure?(["code": 0, "message": "无法将字符串转换为 Data"])
                        }
                    }
                }
            }else {
                Async.main {
                    responseClosure?(["code": 0, "message": "返回Data为空"])
                }
            }
        }
        task.resume()
    }
    
    func requestUploadApi(_ api: Api, fileData: Data, responseClosure: ResponseClosure? = nil) {
        let url = URL(string: api.domain + api.service + api.path)
        let parameters: [String: String] = [
            "type": "jpg"
        ]
//        AF.upload(multipartFormData: { multipartFormData in
//            // 添加文件数据
//            multipartFormData.append(fileData, withName: "file", fileName: "upload.jpg", mimeType: "image/jpeg")
//            // 添加其他参数
//            for (key, value) in parameters {
//                if let valueData = value.data(using: .utf8) {
//                    multipartFormData.append(valueData, withName: key)
//                }
//            }
//        }, to: url!, headers: HTTPHeaders(api.headers))
//        .response { response in
//            // 检查请求结果
//            switch response.result {
//            case .success:
//                if let json = try? JSONSerialization.jsonObject(with: response.data!, options: []) as? [String: Any] {
//                    Async.main {
//                        responseClosure?(json)
//                    }
//                }
//                print("上传成功")
//            case let .failure(error):
//                responseClosure?(["code": 0, "message": "上传失败: \(error)"])
//                print("上传失败: \(error)")
//            }
//        }
    }
    
    static func aesEncrypt(_ req: String, secretKey: String = "9y98b6ikYGczTgnv", iv: String = "0000000000000000") -> String{
        var encryptedBase64 = ""
        do {
            let aes = try AES(key: secretKey.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7)
            let encrypted = try aes.encrypt(req.bytes)
            encryptedBase64 = encrypted.toBase64() ?? "" //将加密结果转成base64形式
        } catch { }
        
        return encryptedBase64
    }
    
    static func aesdecrypt(_ res: String, secretKey: String = "9y98b6ikYGczTgnv", iv: String = "0000000000000000") -> String{
        var decryptStr = ""
        if let encryptedData = Data(base64Encoded: res) {
            do {
                // 初始化AES对象，设置 CBC 模式和 PKCS7 填充
                let aes = try AES(key: secretKey.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7)
                let decryptedBytes = try aes.decrypt(encryptedData.bytes)
                if let decryptedString = String(bytes: decryptedBytes, encoding: .utf8) {
                    decryptStr = decryptedString
                } else {
                    print("无法将解密后的数据转换为字符串")
                }
            } catch {
                print("解密失败: \(error)")
            }
        } else {
            print("Base64解码失败")
        }

        return decryptStr
    }

}
